#include "ast.h"
#include <stdio.h>

string_t OP_NAME[] = {"AND", "OR", "LT", "LE", "GT", "GE", "EQ",
												"NEQ", "PLUS", "MINUS", "TIMES", "DIVIDE"};

string_t PRIMITIVE_TYPE_NAME[] = {"INT", "FLOAT", "CHAR", "STRING", "BOOLEAN"};

ast_decl_t ast_class_decl(int pos, ast_type_t name, list_t var_decls,
													list_t method_decls)
{
		ast_decl_t p = checked_malloc(sizeof(*p));
		p->kind = AST_CLASS_DECL;
		p->pos = pos;
		p->u.class_.name = name;
		p->u.class_.var_decls = var_decls;
		p->u.class_.method_decls = method_decls;
		return p;
}

ast_decl_t ast_var_decl(int pos, ast_type_t type, symbol_t name)
{
		ast_decl_t p = checked_malloc(sizeof(*p));
		p->kind = AST_VAR_DECL;
		p->pos = pos;
		p->u.var.type = type;
		p->u.var.name = name;
		return p;

}

ast_decl_t ast_method_decl(int pos, ast_type_t type, symbol_t name,
														list_t para_decls, list_t var_decls,
														list_t stmts, ast_expr_t ret)
{
		ast_decl_t p = checked_malloc(sizeof(*p));
		p->kind = AST_METHOD_DECL;
		p->pos = pos;
		p->u.method.type = type;
		p->u.method.name = name;
		p->u.method.para_decls = para_decls;
		p->u.method.var_decls = var_decls;
		p->u.method.stmts = stmts;
		p->u.method.ret = ret;
		return p;

}

ast_decl_t ast_para_decl(int pos, ast_type_t type, symbol_t name)
{
		ast_decl_t p = checked_malloc(sizeof(*p));
		p->kind = AST_PARA_DECL;
		p->pos = pos;
		p->u.para.type = type;
		p->u.para.name = name;
		return p;

}


/*	Print Method 	*/
void print_ast_decl(ast_decl_t r, int level)
{
		if(r) {
				switch (r->kind)
				{
					case AST_CLASS_DECL:
						print_ast_class_decl(r, level);
						break;

					case AST_VAR_DECL:
						print_ast_var_decl(r, level);
						break;

					case AST_METHOD_DECL:
						print_ast_method_decl(r, level);
						break;
			
					case AST_PARA_DECL:
						print_ast_para_decl(r, level);
						break;

					default:
						fprintf(stderr, "Error Type\n.");
						break;
				}
		}
}

void print_ast_class_decl(ast_decl_t r, int level)
{
		print_filter(level);
		fprintf(stdout, "|--CLASS_DECL\n");
			
		print_filter(level+1);
		fprintf(stdout, "|--name:\n");
		print_ast_type(r->u.class_.name, level+2);
 
		print_filter(level+1);
		fprintf(stdout, "|--var decls\n");
		list_t var_decls = r->u.class_.var_decls;
		if(var_decls) {
				print_ast_decl((ast_decl_t)var_decls->data, level+2);
				while(var_decls->next) {
						var_decls = var_decls->next;
						print_ast_decl((ast_decl_t)var_decls->data, level+2);
				}
		}

		print_filter(level+1);
		fprintf(stdout, "|--method decls\n");
		list_t method_decls = r->u.class_.method_decls;
		if(method_decls) {
				print_ast_decl((ast_decl_t)method_decls->data, level+2);
				while(method_decls->next) {
						method_decls = method_decls->next;
						print_ast_decl((ast_decl_t)method_decls->data, level+2);
				}
		}
}

void print_ast_var_decl(ast_decl_t r, int level)
{
		print_filter(level);
		fprintf(stdout, "|--VAR_DECL\n");

		print_filter(level+1);
		fprintf(stdout, "|--type\n");
		print_ast_type(r->u.var.type, level+2);

		print_filter(level+1);
		fprintf(stdout, "|--name: %s\n", sym_name(r->u.var.name));
}

void print_ast_method_decl(ast_decl_t r, int level)
{
		print_filter(level);
		fprintf(stdout, "|--METHOD DECL\n");

		print_filter(level+1);
		fprintf(stdout, "|--type\n");
		print_ast_type(r->u.method.type, level+2);

		print_filter(level+1);
		fprintf(stdout, "|--name: %s\n", sym_name(r->u.method.name));

		print_filter(level+1);
		fprintf(stdout, "|--para decls\n");
		list_t para_decls = r->u.method.para_decls;
		if(para_decls) {
				print_ast_decl((ast_decl_t)para_decls->data, level+2);
				while(para_decls->next) {
						para_decls = para_decls->next;
						print_ast_decl((ast_decl_t)para_decls->data, level+2);
				}
		}

		print_filter(level+1);
		fprintf(stdout, "|--var decls\n");
		list_t var_decls = r->u.method.var_decls;
		if(var_decls) {
				print_ast_decl((ast_decl_t)var_decls->data, level+2);
				while(var_decls->next) {
						var_decls = var_decls->next;
						print_ast_decl((ast_decl_t)var_decls->data, level+2);
				}
		}

		print_filter(level+1);
		fprintf(stdout, "|--stmts\n");
		list_t stmts = r->u.method.stmts;
		if(stmts) {
				print_ast_stmt((ast_stmt_t)stmts->data, level+2);
				while(stmts->next) {
						stmts = stmts->next;
						print_ast_stmt((ast_stmt_t)stmts->data, level+2);
				}
		}

		print_filter(level+1);
		fprintf(stdout, "|--return\n");
		print_ast_expr(r->u.method.ret, level+2);
}

void print_ast_para_decl(ast_decl_t r, int level)
{
		print_filter(level);
		fprintf(stdout, "|--PARA DECL\n");

		print_filter(level+1);
		fprintf(stdout, "|--type\n");
		print_ast_type(r->u.para.type, level+2);

		print_filter(level+1);
		fprintf(stdout, "|--name: %s\n", sym_name(r->u.para.name));
}

/* 	End Print Method 	*/

ast_stmt_t ast_stmts_stmt(int pos, list_t stmts)
{
		ast_stmt_t p = checked_malloc(sizeof(*p));
		p->kind = AST_STMTS_STMT;
		p->pos = pos;
		p->u.stmts = stmts;
		return p;
}

ast_stmt_t ast_if_stmt(int pos, ast_expr_t cond, ast_stmt_t if_block,
												ast_stmt_t else_block)
{
		ast_stmt_t p = checked_malloc(sizeof(*p));
		p->kind = AST_IF_STMT;
		p->pos = pos;
		p->u.if_.cond = cond;
		p->u.if_.if_block = if_block;
		p->u.if_.else_block = else_block;
		return p;
}

ast_stmt_t ast_while_stmt(int pos, ast_expr_t cond, ast_stmt_t block)
{
		ast_stmt_t p = checked_malloc(sizeof(*p));
		p->kind = AST_WHILE_STMT;
		p->pos = pos;
		p->u.while_.cond = cond;
		p->u.while_.block = block;
		return p;
}

ast_stmt_t ast_var_assign_stmt(int pos, symbol_t lhs, ast_expr_t rhs)
{
		ast_stmt_t p = checked_malloc(sizeof(*p));
		p->kind = AST_VAR_ASSIGN_STMT;
		p->pos = pos;
		p->u.var_assign.lhs = lhs;
		p->u.var_assign.rhs = rhs;
		return p;
}

ast_stmt_t ast_arr_assign_stmt(int pos, symbol_t lhs_id,
																ast_expr_t lhs_index, ast_expr_t rhs)
{
		ast_stmt_t p = checked_malloc(sizeof(*p));
		p->kind = AST_ARR_ASSIGN_STMT;
		p->pos = pos;
		p->u.arr_assign.lhs_id = lhs_id;
		p->u.arr_assign.lhs_index = lhs_index;
		p->u.arr_assign.rhs = rhs;
		return p;
}

ast_stmt_t ast_call_stmt(int pos, ast_expr_t field, symbol_t name, 
													list_t args)
{
		ast_stmt_t p = checked_malloc(sizeof(*p));
		p->kind = AST_CALL_STMT;
		p->pos = pos;
		p->u.call.field = field;
		p->u.call.name = name;
		p->u.call.args = args;
		return p;
}

/* 	Print Methods */
void print_ast_stmt(ast_stmt_t r, int level)
{
		if(r) {
				switch (r->kind)
				{
						case AST_STMTS_STMT:
							print_ast_stmts_stmt(r, level);
							break;

						case AST_IF_STMT:
							print_ast_if_stmt(r, level);
							break;

						case AST_WHILE_STMT:
							print_ast_while_stmt(r, level);
							break;

						case AST_VAR_ASSIGN_STMT:
							print_ast_var_assign_stmt(r, level);
							break;

						case AST_ARR_ASSIGN_STMT:
							print_ast_arr_assign_stmt(r, level);
							break;

						case AST_CALL_STMT:
							print_ast_call_stmt(r, level);
							break;

						default:
							fprintf(stderr, "Error Type\n.");
							break;
				}
		}
}


void print_ast_stmts_stmt(ast_stmt_t r, int level)
{
		print_filter(level);
		fprintf(stdout, "|--STMTS STMT\n");

		print_filter(level+1);
		fprintf(stdout, "|--stmts\n");
		list_t stmts = r->u.stmts;
		if(stmts) {
				print_ast_stmt(stmts->data, level+2);
				while(stmts->next) {
						stmts = stmts->next;
						print_ast_stmt(stmts->data, level+2);
				}
		}
}

void print_ast_if_stmt(ast_stmt_t r, int level)
{
		print_filter(level);
		fprintf(stdout, "|--IF STMT\n");

		print_filter(level+1);
		fprintf(stdout, "|--condition\n");
		print_ast_expr(r->u.if_.cond, level+2);

		print_filter(level+1);
		fprintf(stdout, "|--if part\n");
		print_ast_stmt(r->u.if_.if_block, level+2);

		print_filter(level+1);
		fprintf(stdout, "|--else part\n");
		print_ast_stmt(r->u.if_.else_block, level+2);
}

void print_ast_while_stmt(ast_stmt_t r, int level)
{
		print_filter(level);
		fprintf(stdout, "|--WHILE STMT\n");

		print_filter(level+1);
		fprintf(stdout, "|--condition\n");
		print_ast_expr(r->u.while_.cond, level+2);

		print_filter(level+1);
		fprintf(stdout, "|--body part\n");
		print_ast_stmt(r->u.while_.block, level+2);
}

void print_ast_var_assign_stmt(ast_stmt_t r, int level)
{
		print_filter(level);
		fprintf(stdout, "|--VAR ASSIGN STMT\n");

		print_filter(level+1);
		fprintf(stdout, "|--lhs name: %s\n", sym_name(r->u.var_assign.lhs));

		print_filter(level+1);
		fprintf(stdout, "|--rhs: \n");
		print_ast_expr(r->u.var_assign.rhs, level+2);
}

void print_ast_arr_assign_stmt(ast_stmt_t r, int level)
{
		print_filter(level);
		fprintf(stdout, "|--ARR ASSIGN STMT\n");

		print_filter(level+1);
		fprintf(stdout, "|--lhs name: %s\n", sym_name(r->u.arr_assign.lhs_id));

		print_filter(level+1);
		fprintf(stdout, "|--lhs index\n");
		print_ast_expr(r->u.arr_assign.lhs_index, level+2);

		print_filter(level+1);
		fprintf(stdout, "|--rhs\n");
		print_ast_expr(r->u.arr_assign.rhs, level+2);
}
		
void print_ast_call_stmt(ast_stmt_t r, int level)
{
		print_filter(level);
		fprintf(stdout, "|--CALL STMT\n");

		print_filter(level+1);
		fprintf(stdout, "|--field\n");
		print_ast_expr(r->u.call.field, level+2);

		print_filter(level+1);
		fprintf(stdout, "|--name: %s\n", sym_name(r->u.call.name));

		print_filter(level+1);
		fprintf(stdout, "|--args\n");
		list_t args = r->u.call.args;
		if(args) {
				print_ast_expr(args->data, level+2);
				while(args->next) {
						args = args->next;
						print_ast_expr(args->data, level+2);
				}
		}
}
/* 	End of Print Methods 	*/

ast_expr_t ast_op_expr(int pos, ast_expr_t left, ast_binop_t op,
												ast_expr_t right)
{
		ast_expr_t p = checked_malloc(sizeof(*p));
		p->kind = AST_OP_EXPR;
		p->pos = pos;
		p->u.op.left = left;
		p->u.op.op = op;
		p->u.op.right = right;
		return p;
}

ast_expr_t ast_not_expr(int pos, ast_expr_t expr)
{
		ast_expr_t p = checked_malloc(sizeof(*p));
		p->kind = AST_NOT_EXPR;
		p->pos = pos;
		p->u.not_ = expr;
		return p;
}

ast_expr_t ast_arr_access_expr(int pos, ast_expr_t arr,ast_expr_t index)
{
		ast_expr_t p = checked_malloc(sizeof(*p));
		p->kind = AST_ARR_ACCESS_EXPR;
		p->pos = pos;
		p->u.arr_access.arr = arr;
		p->u.arr_access.index = index;
		return p;
}

ast_expr_t ast_method_access_expr(int pos, ast_expr_t field, 
																	symbol_t name, list_t args)
{
		ast_expr_t p = checked_malloc(sizeof(*p));
		p->kind = AST_METHOD_ACCESS_EXPR;
		p->pos = pos;
		p->u.method_access.field = field;
		p->u.method_access.name = name;
		p->u.method_access.args = args;
		return p;
}

ast_expr_t ast_arr_length_expr(int pos, ast_expr_t arr)
{
		ast_expr_t p = checked_malloc(sizeof(*p));
		p->kind = AST_ARR_LENGTH_EXPR;
		p->pos = pos;
		p->u.arr_length = arr;
		return p;
}

ast_expr_t ast_idf_expr(int pos, symbol_t name)
{
		ast_expr_t p = checked_malloc(sizeof(*p));
		p->kind = AST_IDF_EXPR;
		p->pos = pos;
		p->u.idf = name;
		return p;
}

ast_expr_t ast_this_expr(int pos)
{
		ast_expr_t p = checked_malloc(sizeof(*p));
		p->kind = AST_THIS_EXPR;
		p->pos = pos;
		return p;
}

ast_expr_t ast_class_init_expr(int pos, symbol_t name)
{
		ast_expr_t p = checked_malloc(sizeof(*p));
		p->kind = AST_CLASS_INIT_EXPR;
		p->pos = pos;
		p->u.class_init = name;
		return p;
}

ast_expr_t ast_arr_init_expr(int pos, ast_type_t type,
															ast_expr_t size)
{
		ast_expr_t p = checked_malloc(sizeof(*p));
		p->kind = AST_ARR_INIT_EXPR;
		p->pos = pos;
		p->u.arr_init.type = type;
		p->u.arr_init.size = size;
		return p;
}

ast_expr_t ast_arr_decl_expr(int pos, list_t arr_decl)
{
		ast_expr_t p = checked_malloc(sizeof(*p));
		p->kind = AST_ARR_DECL_EXPR;
		p->pos = pos;
		p->u.arr_decl = arr_decl; 
		return p;
}

ast_expr_t ast_int_expr(int pos, int val)
{
		ast_expr_t p = checked_malloc(sizeof(*p));
		p->kind = AST_INT_EXPR;
		p->pos = pos;
		p->u.ival = val;
		return p;
}

ast_expr_t ast_float_expr(int pos, float val)
{
		ast_expr_t p = checked_malloc(sizeof(*p));
		p->kind = AST_FLOAT_EXPR;
		p->pos = pos;
		p->u.fval = val;
		return p;
}

ast_expr_t ast_char_expr(int pos, char val)
{
		ast_expr_t p = checked_malloc(sizeof(*p));
		p->kind = AST_CHAR_EXPR;
		p->pos = pos;
		p->u.cval = val;
		return p;
}

ast_expr_t ast_string_expr(int pos, string_t val)
{
		ast_expr_t p = checked_malloc(sizeof(*p));
		p->kind = AST_STRING_EXPR;
		p->pos = pos;
		p->u.sval = val;
		return p;
}

ast_expr_t ast_bool_expr(int pos, bool val)
{
		ast_expr_t p = checked_malloc(sizeof(*p));
		p->kind = AST_BOOL_EXPR;
		p->pos = pos;
		p->u.bval = val;
		return p;
}


/* 	Print Methods */
void print_ast_expr(ast_expr_t r, int level)
{
		if(r) {
				switch (r->kind)
				{
					case AST_OP_EXPR:
						print_ast_op_expr(r, level);
						break;
				
					case AST_NOT_EXPR:
						print_ast_not_expr(r, level);
						break;

					case AST_ARR_ACCESS_EXPR:
						print_ast_arr_access_expr(r, level);
						break;

					case AST_METHOD_ACCESS_EXPR:
						print_ast_method_access_expr(r, level);
						break;

					case AST_ARR_LENGTH_EXPR:
						print_ast_arr_length_expr(r, level);
						break;

					case AST_IDF_EXPR:
						print_ast_idf_expr(r, level);
						break;

					case AST_THIS_EXPR:
						print_ast_this_expr(r, level);
						break;

					case AST_CLASS_INIT_EXPR:
						print_ast_class_init_expr(r, level);
						break;

					case AST_ARR_INIT_EXPR:
						print_ast_arr_init_expr(r, level);
						break;

					case AST_ARR_DECL_EXPR:
						print_ast_arr_decl_expr(r, level);
						break;

					case AST_INT_EXPR:
						print_ast_int_expr(r, level);
						break;

					case AST_FLOAT_EXPR:
						print_ast_float_expr(r, level);
						break;

					case AST_CHAR_EXPR:
						print_ast_char_expr(r, level);
						break;

					case AST_STRING_EXPR:
						print_ast_string_expr(r, level);
						break;

					case AST_BOOL_EXPR:
						print_ast_bool_expr(r, level);
						break;

					default:
						fprintf(stderr, "Error Type\n.");
						break;
				}
		}
}

void print_ast_op_expr(ast_expr_t r, int level)
{
		print_filter(level);
		fprintf(stdout, "|--OP EXPR\n");

		print_filter(level+1);
		fprintf(stdout, "|--left expr\n");
		print_ast_expr(r->u.op.left, level+2);
		
		print_filter(level+1);
		fprintf(stdout, "|--op: %s\n", OP_NAME[r->u.op.op]);

		print_filter(level+1);
		fprintf(stdout, "|--right expr\n");
		print_ast_expr(r->u.op.right, level+2);
}

void print_ast_not_expr(ast_expr_t r, int level)
{
		print_filter(level);
		fprintf(stdout, "|--NOT EXPR\n");

		print_filter(level+1);
		fprintf(stdout, "|--expr\n");
		print_ast_expr(r->u.not_, level+2);
}

void print_ast_arr_access_expr(ast_expr_t r, int level)
{
		print_filter(level);
		fprintf(stdout, "|--ARR ACCESS EXPR\n");

		print_filter(level+1);
		fprintf(stdout, "|--arr expr\n");
		print_ast_expr(r->u.arr_access.arr, level+2);

		print_filter(level+1);
		fprintf(stdout, "|--index expr\n");
		print_ast_expr(r->u.arr_access.index, level+2);
}

void print_ast_method_access_expr(ast_expr_t r, int level)
{
		print_filter(level);
		fprintf(stdout, "|--METHOD ACCESS EXPR\n");

		print_filter(level+1);
		fprintf(stdout, "|--field expr\n");
		print_ast_expr(r->u.method_access.field, level+2);

		print_filter(level+1);
		fprintf(stdout, "|--name: %s\n", sym_name(r->u.method_access.name));

		print_filter(level+1);
		fprintf(stdout, "|--args\n");
		list_t args = r->u.method_access.args;
		if(args) {
				print_ast_expr(args->data, level+2);
				while(args->next) {
						args = args->next;
						print_ast_expr(args->data, level+2);
				}
		}
}

void print_ast_arr_length_expr(ast_expr_t r, int level)
{
		print_filter(level);
		fprintf(stdout, "|--ARR LENGTH EXPR\n");

		print_filter(level+1);
		fprintf(stdout, "|--arr expr\n");
		print_ast_expr(r->u.arr_length, level+2);
}

void print_ast_idf_expr(ast_expr_t r, int level)
{
		print_filter(level);
		fprintf(stdout, "|--IDF EXPR\n");
		print_filter(level+1);
		fprintf(stdout, "|--idf name: %s\n", sym_name(r->u.idf));
}

void print_ast_this_expr(ast_expr_t r, int level)
{
		print_filter(level);
		fprintf(stdout, "|--THIS EXPR\n");
}

void print_ast_class_init_expr(ast_expr_t r, int level)
{
		print_filter(level);
		fprintf(stdout, "|--CLASS INIT\n");
		print_filter(level+1);
		fprintf(stdout, "|--class name: %s\n", sym_name(r->u.class_init));
}

void print_ast_arr_init_expr(ast_expr_t r, int level)
{
		print_filter(level);
		fprintf(stdout, "|--ARR INIT EXPR\n");

		print_filter(level+1);
		fprintf(stdout, "|--type\n");
		print_ast_type(r->u.arr_init.type, level+2);

		print_filter(level+1);
		fprintf(stdout, "|--size\n");
		print_ast_expr(r->u.arr_init.size, level+2);
}

void print_ast_arr_decl_expr(ast_expr_t r, int level)
{
		print_filter(level);
		fprintf(stdout, "|--ARR DECL EXPR\n");

		print_filter(level+1);
		fprintf(stdout, "|--arr decl\n");
		list_t arr_decl = r->u.arr_decl;
		if(arr_decl) {
				print_ast_expr(arr_decl->data, level+2);
				while(arr_decl->next) {
						arr_decl = arr_decl->next;
						print_ast_expr(arr_decl->data, level+2);
				}
		}
}

void print_ast_int_expr(ast_expr_t r, int level)
{
		print_filter(level);
		fprintf(stdout, "|--INT EXPR\n");
		print_filter(level+1);
		fprintf(stdout, "|--value: %d\n", r->u.ival);
}

void print_ast_float_expr(ast_expr_t r, int level)
{
		print_filter(level);
		fprintf(stdout, "|--FLOAT EXPR\n");
		print_filter(level+1);
		fprintf(stdout, "|--value: %f\n", r->u.fval);
}

void print_ast_char_expr(ast_expr_t r, int level)
{
		print_filter(level);
		fprintf(stdout, "|--CHAR EXPR\n");
		print_filter(level+1);
		fprintf(stdout, "|--value: %c\n", r->u.cval);
}

void print_ast_string_expr(ast_expr_t r, int level)
{
		print_filter(level);
		fprintf(stdout, "|--STRING EXPR\n");
		print_filter(level+1);
		fprintf(stdout, "|--value: %s\n", r->u.sval);
}

void print_ast_bool_expr(ast_expr_t r, int level)
{
		print_filter(level);
		fprintf(stdout, "|--BOOL EXPR\n");
		print_filter(level+1);
		fprintf(stdout, "|--value: %d\n", r->u.bval);
}

/* 	End of Print Methods */


ast_type_t ast_primitive_type(int pos, ast_primitive_type_t primitive)
{
		ast_type_t p = checked_malloc(sizeof(*p));
		p->kind = AST_PRIMITIVE_TYPE;
		p->pos = pos;
		p->u.primitive = primitive;
		return p;
}

ast_type_t ast_class_type(int pos, symbol_t class_name)
{
		ast_type_t p = checked_malloc(sizeof(*p));
		p->kind = AST_CLASS_TYPE;
		p->pos = pos;
		p->u.class_ = class_name;
		return p;
}

ast_type_t ast_array_type(int pos, ast_primitive_type_t primitive)
{
		ast_type_t p = checked_malloc(sizeof(*p));
		p->kind = AST_ARRAY_TYPE;
		p->pos = pos;
		p->u.array = primitive;
		return p;
}


/* 	Print Methods */
void print_ast_type(ast_type_t r, int level)
{
		if(r) {
				switch (r->kind)
				{
					case AST_PRIMITIVE_TYPE:
						print_ast_primitive_type(r, level);
						break;

					case AST_CLASS_TYPE:
						print_ast_class_type(r, level);
						break;

					case AST_ARRAY_TYPE:
						print_ast_array_type(r, level);
						break;
			
					default:
						fprintf(stderr, "Error Type\n.");
						break;
				}
		}
}

void print_ast_primitive_type(ast_type_t r, int level)
{
		print_filter(level);
		fprintf(stdout, "|--PRIMITIVE TYPE\n");
		print_filter(level+1);
		fprintf(stdout, "|--type name: %s\n", PRIMITIVE_TYPE_NAME[r->u.primitive]);
}

void print_ast_class_type(ast_type_t r, int level)
{
		print_filter(level);
		fprintf(stdout, "|--CLASS TYPE\n");
		print_filter(level+1);
		fprintf(stdout, "|--class name: %s\n", sym_name(r->u.class_));
}

void print_ast_array_type(ast_type_t r, int level)
{
		print_filter(level);
		fprintf(stdout, "|--ARRAY TYPE\n");
		print_filter(level+1);
		fprintf(stdout, "|--type name: %s[]\n", PRIMITIVE_TYPE_NAME[r->u.array]);
}

/* 	End of Print Methods */

void print_filter(int level)
{
		int i;
		for (i=0; i<level*5; i++)
			fprintf(stdout, " ");
}
